﻿using System;
using System.Web;
using System.Security.Principal;
using System.Web.Security;

using LDAP.Entity;

namespace LDAP
{
    public class Auth
    {
        /// <summary>
        /// 2011-04-06修改为public RequestTime，场景：/redirect.aspx在设置cookie要指定域
        /// </summary>
        public static readonly string CookieDomain = ".simpleyeung.com";//Utility.FormsAuthenticationSessionService.Instance.GetCookieDomain()
        
        /// <summary>
        /// 2010-07-06增加
        /// </summary>
        public static void ClearAuthentication()
        {
            //Utility.FormsAuthenticationSessionService.Instance.Clear();
            SetLogOut();
        }

        /// <summary>
        /// 退出登录
        /// </summary>
        public static void SetLogOut()
        {
            if (HttpContext.Current == null)
                return;
            FormsAuthentication.SignOut();
            var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName);
            if (!string.IsNullOrEmpty(FormsAuthentication.CookieDomain))
                authCookie.Domain = FormsAuthentication.CookieDomain;
            authCookie.HttpOnly = true;
            authCookie.Expires = DateTime.Now.AddDays(-1d);
            HttpContext.Current.Response.Cookies.Add(authCookie);
        }

        /// <summary>
        /// 设置登录(票证中的用户特定的数据默认为"All")
        /// </summary>
        /// <param name="userId">存储在票证中的用户标识。</param>
        /// <param name="isPersistent">如果票证将存储在持久性 Cookie（跨浏览器会话保存），则为 true；否则为 false。如果该票证存储在 URL 中，将忽略此值。</param>
        public static void SetLogOn(string userId, bool isPersistent)
        {
            SetLogOn(userId, isPersistent, "All");
        }

        /// <summary>
        /// 设置登录
        /// </summary>
        /// <param name="userId">存储在票证中的用户标识。</param>
        /// <param name="isPersistent">如果票证将存储在持久性 Cookie（跨浏览器会话保存），则为 true；否则为 false。如果该票证存储在 URL 中，将忽略此值。</param>
        /// <param name="userData">存储在票证中的用户特定的数据。默认为"All"</param>
        public static void SetLogOn(string userId, bool isPersistent, string userData)
        {
            SetLogOn(userId, isPersistent, userData, DateTime.Now.AddDays(isPersistent ? 30 : 1));
        }

        /// <summary>
        /// 设置登录
        /// </summary>
        /// <param name="userId">存储在票证中的用户标识。</param>
        /// <param name="isPersistent">如果票证将存储在持久性 Cookie（跨浏览器会话保存），则为 true；否则为 false。如果该票证存储在 URL 中，将忽略此值。</param>
        /// <param name="userData">存储在票证中的用户特定的数据。</param>
        /// <param name="expiration">票证过期时的本地日期和时间。</param>
        public static void SetLogOn(string userId, bool isPersistent, string userData, DateTime expiration)
        {
            if (HttpContext.Current == null)
                return;

            var response = HttpContext.Current.Response;
            var request = HttpContext.Current.Request;
            var ticket = new FormsAuthenticationTicket(
                1
               , userId.ToString()
               , DateTime.Now
               , expiration
               , true
               , userData
               , FormsAuthentication.FormsCookiePath
               );
            var encryptedTicket = FormsAuthentication.Encrypt(ticket);
            var authCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket)
                                 {
                                     HttpOnly = true,
                                     Expires = expiration
                                 };
            if (!string.IsNullOrEmpty(FormsAuthentication.CookieDomain))
                authCookie.Domain = FormsAuthentication.CookieDomain;

            var identity = new FormsIdentity(ticket);
            var user = new GenericPrincipal(identity, new[] { userData });
            HttpContext.Current.User = user;

            response.Cookies.Add(authCookie);
            response.AppendHeader("P3P", "CP=CAO PSA OUR");
        }

        /// <summary>
        /// 2010-07-16 取消天数必传 RequestTime
        /// </summary>
        /// <param name="user"></param>
        /// <param name="days"></param>
        public static void SetAuthentication(User user, int? days)
        {
            //Utility.FormsAuthenticationSessionService.Instance.Set(user, days);            
            SetLogOn(user.Id, days != null, GetStringFromEntity(user));
        }

        /// <summary>
        /// 根据基本信息构成实体
        /// </summary>
        /// <param name="str"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        private static User GetEntityFromString(string str, string userId)
        {
            if (string.IsNullOrEmpty(str))
                return null;

            try
            {
                string[] arr = str.Split('^');

                var entry = new User
                                {
                                    Id = arr[0],
                                    UserName = arr[1],
                                    Email = arr[3],
                                    DeptName = arr[4]
                                };
                return entry;
            }
            catch (Exception ex)
            {
                //从其他站点过来用户，则帮忙设置重新登录，并记录用户基本信息
                //by Simple 2012-02-10
                //var user = BizUser.GetByKey(userId);
                //SetAuthentication(user, null);
                //return user;
                return null;
            }
        }

        /// <summary>
        /// 根据实体获取存储cookie内的基本信息
        /// </summary>
        /// <param name="entry"></param>
        /// <returns></returns>
        private static string GetStringFromEntity(User entry)
        {
            return string.Format("{0}^{1}^{2}^{3}^{4}",
                entry.Id,
                entry.UserName,
                ((uint)GetUnixMicTime(DateTime.Now)),
                entry.Email,
                entry.DeptName
                );
        }

        /// <summary>
        /// 返回带秒的小数的时间
        /// </summary>
        /// <param name="time"></param>
        /// <returns></returns>
        public static double GetUnixMicTime(DateTime time)
        {
            //DateTime sTime = new DateTime(1970, 1, 1, 0, 0, 0);
            //TimeSpan eTime = time - sTime;
            //return (eTime.TotalSeconds);

            // by tongchao 修复时区bug
            TimeSpan ts = time - TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(1970, 1, 1));
            return ts.TotalSeconds;

        }

        /// <summary>
        /// 获取当前已经登录的用户信息
        /// </summary>
        /// <returns>
        /// 已经登录的用户信息，未登录则返回null
        /// </returns>
        public static string GetCurrentUserId(out string userData)
        {
            var context = HttpContext.Current;
            var userId = "";
            userData = string.Empty;
            if (context == null)
                return userId;

            var cookie = context.Request.Cookies[FormsAuthentication.FormsCookieName];
            if (cookie == null || string.IsNullOrEmpty(cookie.Value))
                return userId;

            try
            {
                var ticket = FormsAuthentication.Decrypt(cookie.Value);
                userId = ticket.Name;
                userData = ticket.UserData;
            }
            catch (Exception ex)
            {
                userId = "";
                userData = string.Empty;
            }

            if (string.IsNullOrEmpty(userId))
            {
                SetLogOut();
                return userId;
            }

            return userId;
        }

        /// <summary>
        /// 2010-08-23 返回类修改为UserDecorator RequestTime
        /// </summary>
        /// <returns></returns>
        public static User GetUser()
        {
            //return new UserDecorator(new User(){UserType = 100, UserId = 2, UserName = "张靓颖"});

            if (HttpContext.Current == null)//2010-07-27 增加该判断，为适应在APP的时候使用 RequestTime
                return null;
            
            string str;
            string userId = GetCurrentUserId(out str);
            if (string.IsNullOrEmpty(userId))
                return null;
            return new User(GetEntityFromString(str, userId));
        }
    }
}
